/*
 * FSWUniCEUB - 2008
 * 
 * Este arquivo é de propriedade da Fábrica de Software do UniCEUB
 * 
 * Para mais informações entre em contato com a coordenação do
 * curso de Ciência da Computação da instituição.
 */

package br.uniceub.fsw.seguranca.facade;

import br.uniceub.fsw.arquitetura.persistencia.transacao.Transacao;
import br.uniceub.fsw.seguranca.dao.AcessoDAO;
import br.uniceub.fsw.seguranca.dao.ModuloDAO;
import br.uniceub.fsw.seguranca.dao.GrupoDAO;
import br.uniceub.fsw.seguranca.vo.AcessoVO;
import br.uniceub.fsw.seguranca.vo.ModuloVO;
import br.uniceub.fsw.seguranca.vo.GrupoVO;
import br.uniceub.fsw.util.TabelaHtml;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Facade da entidade Acesso.
 * 
 * @author Bruno Schifer Bernardi
 */
public class AcessoFacade {
    /**
     * Mensagem de retorno do sistema.
     */
    private String message;

    /**
     * Value object do acesso.
     */
    private AcessoVO acesso;
    
    /**
     * Objeto de acesso aos dados de acesso.
     */
    private AcessoDAO acessoDao;
    
    /**
     * Construtor da classe.
     */
    public AcessoFacade() {
        this.acessoDao = new AcessoDAO();
    }
    
    /**
     * Getter da mensagem de retorno.
     * 
     * @return Mensagem de retorno.
     */
    public String getMessage() {
        String retorno = null;
        if(this.message == null || this.message.equals("")) {
            retorno = "&nbsp";
        } else {
            retorno = this.message;
        }
        return retorno;
    }

    /**
     * Setter da mensagem de retorno.
     * 
     * @param message Mensagem de retorno.
     */
    public void setMessage(String message) {
        this.message = message;
    }
    
    /**
     * Responsável por executar a operação selecionada pelo usuário.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void operacao(HttpServletRequest req, HttpServletResponse resp) {
        String oper = req.getParameter("operacao");

        if(oper != null)
        {
            if (oper.equals("consultar")) {
                this.consultar(req, resp);
            }
            if (oper.equals("incluir")) {
                this.incluir(req, resp);
            }
            if (oper.equals("alterar")) {
                this.alterar(req, resp);
            }
            if (oper.equals("excluir")) {
                this.excluir(req, resp);
            }
            if (oper.equals("confirmar")) {
                this.confirmar(req, resp);
            }
        }
    }

    /**
     * Retorna o acesso.
     * 
     * @return Objeto acesso.
     */
    public AcessoVO getAcesso() {
        return this.acesso;
    }
    
    /**
     * Seta o acesso.
     * 
     * @param acesso Objeto acesso.
     */
    public void setAcesso(AcessoVO acesso) {
        this.acesso = acesso;
    }
    
    /**
     * Consultar um acesso.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void consultar(HttpServletRequest req, HttpServletResponse resp) {
        String idAcessoTmp = req.getParameter("idAcesso");
        
        Integer idAcesso = null;
        
        if(idAcessoTmp == null || idAcessoTmp.equals("")) {
            return;
        } else {
            idAcesso = Integer.parseInt(idAcessoTmp);
        }
        
        this.acesso = acessoDao.consultarPorId(idAcesso);
    }

    /**
     * Incluir um acesso.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void incluir(HttpServletRequest req, HttpServletResponse resp) {
        String cdModulo = req.getParameter("cdModulo");
        String cdGrupo = req.getParameter("cdGrupo");

        acesso = new AcessoVO();
        acesso.setCdGrupo(Integer.parseInt(cdGrupo.equals("")?null:cdGrupo));
        acesso.setCdModulo(Integer.parseInt(cdModulo.equals("")?null:cdModulo));
        
        String mensagem = null;
        
        if(cdGrupo == null || cdGrupo.equals("")) {
            mensagem = "Grupo obrigatório.";
        } else if(cdModulo == null || cdModulo.equals("")) {
            mensagem = "Usuário obrigatório.";
        }
        
        if(mensagem == null || mensagem.equals("")) {
            try {
                Transacao.iniciar();

                acessoDao.inserir(acesso);

                Transacao.efetivar();

                mensagem = "Acesso incluído com sucesso.";
            } catch (Exception ex) {
                Transacao.desfazer();

                mensagem = "Problema na inclusão do acesso: " + ex.getMessage();
            }
        } else {
            acesso = null;
        }
        
        this.message = mensagem;
    }

    /**
     * Alterar um acesso.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void alterar(HttpServletRequest req, HttpServletResponse resp) {
        String idAcesso = req.getParameter("idAcesso");
        String cdModulo = req.getParameter("cdModulo");
        String cdGrupo = req.getParameter("cdGrupo");

        acesso = new AcessoVO();
        acesso.setIdAcesso(Integer.parseInt(idAcesso));
        acesso.setCdGrupo(Integer.parseInt(cdGrupo.equals("")?null:cdGrupo));
        acesso.setCdModulo(Integer.parseInt(cdModulo.equals("")?null:cdModulo));
        
        String mensagem = null;
        
        if(cdGrupo == null || cdGrupo.equals("")) {
            mensagem = "Grupo obrigatório.";
        } else if(cdModulo == null || cdModulo.equals("")) {
            mensagem = "Usuário obrigatório.";
        }
        
        if(mensagem == null || mensagem.equals("")) {
            try {
                Transacao.iniciar();

                acessoDao.alterar(acesso);

                Transacao.efetivar();

                mensagem = "Acesso alterado com sucesso.";
            } catch (Exception ex) {
                Transacao.desfazer();

                mensagem = "Problema na alteração do acesso: " + ex.getMessage();
            }
        } else {
            acesso = null;
        }
        
        this.message = mensagem;
    }

    /**
     * Excluir um acesso.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void excluir(HttpServletRequest req, HttpServletResponse resp) {
        String idAcesso = req.getParameter("idAcesso");

        acesso = new AcessoVO();
        acesso.setIdAcesso(Integer.parseInt(idAcesso));
        
        String mensagem = null;
        
        try {
            Transacao.iniciar();
            
            acessoDao.excluir(acesso);
            
            Transacao.efetivar();
            
            mensagem = "Acesso excluído com sucesso.";
        } catch (Exception ex) {
            Transacao.desfazer();
            
            mensagem = "Problema na exclusão do acesso: " + ex.getMessage();
        }
        
        this.acesso = null;
        
        this.message = mensagem;
    }
    
    /**
     * Confirmar a exclusão de acesso.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void confirmar(HttpServletRequest req, HttpServletResponse resp) {
        String idAcesso = req.getParameter("idAcesso");
        String cdModulo = req.getParameter("cdModulo");
        String cdGrupo = req.getParameter("cdGrupo");

        acesso = new AcessoVO();
        acesso.setIdAcesso(Integer.parseInt(idAcesso));
        acesso.setCdGrupo(Integer.parseInt(cdGrupo));
        acesso.setCdModulo(Integer.parseInt(cdModulo));
    }

    /**
     * Retorna uma lista de acessos a partir de parâmetros da tela
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     * @return objeto tabela com as informações necessárias
     */
    public TabelaHtml consultarAcessos(HttpServletRequest req, HttpServletResponse resp) {
        String cdModulo = req.getParameter("cdModulo");
        String cdGrupo = req.getParameter("cdGrupo");
        
        if((cdModulo != null && !cdModulo.equals("")) ||
                (cdGrupo != null && !cdGrupo.equals(""))) {
            TabelaHtml tabela = new TabelaHtml();
            
            tabela.setCampoRetorno("idAcesso");
            
            tabela.adicionarTitulo("Id");
            tabela.adicionarTamanho(0);
            tabela.adicionarTipo("Integer");
            tabela.adicionarStatus(false);

            tabela.adicionarTitulo("Módulo");
            tabela.adicionarTamanho(50);
            tabela.adicionarTipo("String");
            tabela.adicionarStatus(true);
            
            tabela.adicionarTitulo("Grupo");
            tabela.adicionarTamanho(50);
            tabela.adicionarTipo("String");
            tabela.adicionarStatus(true);
            
            tabela.gravarCampos();
            
            AcessoVO exemplo = new AcessoVO();
            
            exemplo.setCdGrupo(cdGrupo.equals("")?null:Integer.parseInt(cdGrupo));
            exemplo.setCdModulo(cdModulo.equals("")?null:Integer.parseInt(cdModulo));
            
            // Lista de acessos
            List<AcessoVO> acessos = acessoDao.consultarPorExemplo(exemplo);
            
            // TODO: ordenar a lista de acessos por níveis hierarquicos
            
            // Adiciona os valores de cada acesso nas listas de ids e nomes
            for(int i = 0; i < acessos.size(); i++) {
                tabela.adicionarRegistro(converterVoParaString(acessos.get(i)));
            }

            return tabela;
        }
        
        return null;
    }
    
    /**
     * Retorna uma lista de usuários ordenada por nome
     * 
     * @return lista com as informações necessárias
     */
    public List<List> consultarModulos() {
        List<List> lista = new ArrayList<List>();

        ModuloDAO moduloDao = new ModuloDAO();
        
        List<ModuloVO> modulos = moduloDao.consultarModulosOrdenadoPorNome();
        
        for(int i = 0; i < modulos.size(); i++) {
            List<String> registro = new ArrayList<String>();
            registro.add(modulos.get(i).getIdModulo().toString());
            registro.add(modulos.get(i).getNoModulo());
            
            lista.add(registro);
        }
        
        return lista;
    }
    
    /**
     * Retorna uma lista de grupos ordenada por nome
     * 
     * @return lista com as informações necessárias
     */
    public List<List> consultarGrupos() {
        List<List> lista = new ArrayList<List>();

        GrupoDAO grupoDao = new GrupoDAO();
        
        List<GrupoVO> grupos = grupoDao.consultarGruposOrdenadoPorNome();
        
        for(int i = 0; i < grupos.size(); i++) {
            List<String> registro = new ArrayList<String>();
            registro.add(grupos.get(i).getIdGrupo().toString());
            registro.add(grupos.get(i).getNoGrupo());
            
            lista.add(registro);
        }
        
        return lista;
    }
    
    public String pegarNomeHierarquicoModulo(ModuloVO modulo) {
        String nomeHierarquico = "";
        
        ModuloVO pai = modulo.getModuloPai();
        
        int nivel = 0;
        
        String espaco = "&nbsp;&nbsp;&nbsp;";
        
        // Pega o número de níveis
        while(pai != null) {
            pai = pai.getModuloPai();
            nivel++;
        }
        
        pai = modulo.getModuloPai();

        String espacos = "";

        for(int i = nivel; i > 0; i--) espacos += espaco;
        
        nomeHierarquico = espacos + modulo.getNoModulo();
        
        while(pai != null) {
            espacos = "";
            
            nivel--;
            
            for(int i = nivel; i > 0; i--) espacos += espaco;
            
            nomeHierarquico = espacos + pai.getNoModulo() + "<br>" + nomeHierarquico;
            
            pai = pai.getModuloPai();
        }
        
        return nomeHierarquico;
    }
    
    /**
     * Transforma os campos de um VO em uma lista de Strings
     * 
     * @return lista de strings com os valores em ordem
     */
    public List<String> converterVoParaString(AcessoVO acesso) {
        List<String> valores = new ArrayList<String>();
        
        valores.add(acesso.getIdAcesso().toString());
        valores.add(pegarNomeHierarquicoModulo(acesso.getModulo()));
        valores.add(acesso.getGrupo().getNoGrupo());
        
        return valores;
    }
}
